<?php

namespace app\common\service\course;

use app\common\enums\LexiconStatusEnum;
use app\common\enums\MemorizeModeEnum;
use app\common\enums\WordLearnTypeEnum;
use app\common\model\banxi\core\CoreMyLexicon;
use app\common\model\banxi\course\Lexicon;
use app\common\model\banxi\learn\LearnSkRecord;
use app\common\model\banxi\learn\LearnSkWordRecord;
use app\common\model\banxi\learn\LearnWordMemorizeRecord;
use app\common\service\ApiService;

class LexiconService extends ApiService
{

    public function wrapperLexiconBase($dataList, $accountId = null, $accountType = null)
    {
        if (!$dataList) {
            return [];
        }

        $courseDataMap = [];
        foreach ($dataList as $item) {
            $courseDataMap[$item['courseId']][] = $item;
        }

        $lexiconBaseList = [];
        foreach ($courseDataMap as $courseId => $dataWords) {
            $wordList = array_map(function ($dataWord) {
                return $dataWord['word'];
            }, $dataWords);
            $lexicon = new Lexicon();
            $lexiconList = $lexicon->listBaseInfoByCourseAndWords($courseId, $wordList)->toArray();
            $lexiconBaseList = array_merge($lexiconBaseList, $lexiconList);
        }
        $words = array_map(function ($item) {
            return $item['word'];
        }, $lexiconBaseList);


        if (!empty($accountId) && $accountType !== null) {
            $coreMyLexicon = new CoreMyLexicon();
            $collectWords = $coreMyLexicon->getCollectByAccountList($accountId, $accountType, $words);
            foreach ($lexiconBaseList as &$item) {
                $item['isCollect'] = in_array($item['word'], $collectWords);
            }
        }

        foreach ($dataList as &$value) {
            $matchedLexiconBase = null;
            foreach ($lexiconBaseList as $lexiconBase) {
                if ($lexiconBase['word'] === $value['word']) {
                    $matchedLexiconBase = $lexiconBase;
                    break;
                }
            }

            // 如果找到匹配的基础信息，则设置到数据对象中
            $value['lexiconBase'] = [
                'word' => $matchedLexiconBase['word'] ?? '',
                'phonetic' => $matchedLexiconBase['phonetic'] ?? '',
                'wordAudio' => $matchedLexiconBase['wordAudio'] ?? '',
                'translation' => $matchedLexiconBase['translation'] ?? '',
                'isCollect' => $matchedLexiconBase['isCollect'] ?? false,
            ];

        }
        return $dataList;

    }

    /**
     * 获取上课记录所学单词
     *
     * @param int $skRecordId 上课记录ID
     * @return array
     */
    public function getSkRecordWords($skRecordId)
    {
        // 1. 根据ID获取上课记录
        $LearnSkRecordModel = new LearnSkRecord();
        $learnSkRecord = $LearnSkRecordModel->where('id', $skRecordId)->find();
        if (empty($learnSkRecord)) {
            getResponseException('操作太频繁啦,上课记录不存在', [], 1, 'ERROR');
        }

        // 2. 获取该上课记录中学过的单词列表
        $LearnSkWordRecordModel = new LearnSkWordRecord();
        $words = $LearnSkWordRecordModel
            ->where('skRecordId', $skRecordId)
            ->where('wordLearnType', WordLearnTypeEnum::E3)
            ->column('word');

        // 3. 如果没有学过单词，返回空列表
        if (empty($words)) {
            return [];
        }
        // 4. 解析实际课程ID列表
        $actualCourseIdList = $learnSkRecord['actualCourseIdList'];
        if (empty($actualCourseIdList)) {
            return [];
        }

        // 5. 根据课程ID列表和单词列表获取单词详细信息
        $lexiconModel = new Lexicon();
        $wordList = $lexiconModel
            ->where('courseId', 'in', $actualCourseIdList)
            ->where('word', 'in', $words)
            ->select();

        return $wordList;
    }

    /**
     * 获取上课记录所学单词（按首字母分组）
     *
     * @param int $skRecordId 上课记录ID
     * @return array
     */
    public function getSkRecordFirstLetterWordsData($skRecordId)
    {
        // 获取上课记录所学单词
        $lexiconList = $this->getSkRecordWords($skRecordId);

        // 按首字母分组
        return $this->convertToFirstLetterStructure($lexiconList);
    }

    /**
     * 查询-课程单词（首字母模式）
     *
     * @param int $courseId 课程ID
     * @param int|null $studentId 学员ID 如果传入则代表是查询学员所学单词（教练教的或者学员学的）
     * @return array 按首字母分组的单词结构
     */
    public function listFirstLetterStructureByCourse($courseId, $studentId = null)
    {
        // 获取单词列表
        $lexiconList = $this->listLexiconByCourse($courseId, $studentId);

        // 数据转换，按首字母分组
        return $this->convertToFirstLetterStructure($lexiconList);
    }

    /**
     * 查询课程单词列表
     *
     * @param int $courseId 课程ID
     * @param int|null $studentId 学员ID
     * @return array 单词列表
     */
    public function listLexiconByCourse($courseId, $studentId = null)
    {
        $lexiconModel = new Lexicon();
        if (!$studentId) {
            // 查询课程中启用状态的单词
            return $lexiconModel
                ->where('courseId', $courseId)
                ->where('status', LexiconStatusEnum::E1) // 1 对应 LexiconStatus.E1 启用状态
                ->order('id', 'asc')
                ->select()
                ->toArray();
        }

        // 查询学员在课程中学过的单词
        $words = LearnWordMemorizeRecord::where('studentId', $studentId)
            ->where('courseId', $courseId)
            ->where('memorizeMode', MemorizeModeEnum::E1) // 1 对应 MemorizeMode.E1
            ->distinct(true)
            ->column('word');

        if (empty($words)) {
            return [];
        }

        // 根据课程ID和单词列表查询单词
        return $lexiconModel
            ->where('courseId', $courseId)
            ->whereIn('word', $words)
            ->order('id', 'asc')
            ->select()
            ->toArray();
    }

    /**
     * 将单词列表转换为首字母分组结构
     *
     * @param array $lexiconList 单词列表
     * @return array
     */
    private function convertToFirstLetterStructure($lexiconList)
    {
        if (empty($lexiconList)) {
            return [];
        }

        // 按首字母分组
        $grouped = [];
        foreach ($lexiconList as $lexicon) {
            // 获取单词首字母（转为大写）
            $firstLetter = strtoupper(substr($lexicon['word'], 0, 1));
            // 如果不是字母，则归为其他组
            if (!ctype_alpha($firstLetter)) {
                $firstLetter = '#';
            }

            if (!isset($grouped[$firstLetter])) {
                $grouped[$firstLetter] = [
                    'firstLetter' => $firstLetter,
                    'wordList' => []
                ];
            }

            $grouped[$firstLetter]['wordList'][] = $lexicon;
        }

        // 按首字母排序
        ksort($grouped);

        // 重新索引并返回
        return array_values($grouped);
    }

}
